package com.mgq.netty.chat.server;

import com.mgq.netty.chat.handler.*;
import com.mgq.netty.chat.protocol.MessageCodecShare;
import com.mgq.netty.chat.protocol.ProtocolFrameDecoder;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;

/**
 * @author MaGuangQi
 * @description
 * @date 2021-12-07 16:58
 **/
@Slf4j
public class ChatServer {
    public static void main(String[] args) throws InterruptedException {
        //注意,这样写,就是多个channel共用一个handler,由于我们ProtocolFrameDecoder不是共享的,所以不能使用一个,而是一个channel对应一个
       // ProtocolFrameDecoder protocolFrameDecoder = new ProtocolFrameDecoder();
        //共享的handler
        LoggingHandler LOG_HANDLER = new LoggingHandler();
        MessageCodecShare MES_CODEC = new MessageCodecShare();

        LoginRequestMessageHandler LOGIN_HANDLER = new LoginRequestMessageHandler();
        ChatRequestMessageHandler CHAT_HANDLER = new ChatRequestMessageHandler();
        GroupCreateRequestMessageHandler GROUP_CREATE_HANDLER = new GroupCreateRequestMessageHandler();
        GroupJoinRequestMessageHandler GROUP_JOIN_HANDLER = new GroupJoinRequestMessageHandler();
        GroupChatRequestMessageHandler GROUP_CHAT_HANDLER = new GroupChatRequestMessageHandler();
        QuitHandler QUIT_HANDLER = new QuitHandler();
        EventLoopGroup boss = new NioEventLoopGroup();
        EventLoopGroup worker = new NioEventLoopGroup();
        ChannelFuture future = new ServerBootstrap()
                .group(boss, worker)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel ch) throws Exception {
                        ch.pipeline().addLast(new ProtocolFrameDecoder());
                        ch.pipeline().addLast(LOG_HANDLER);
                        ch.pipeline().addLast(MES_CODEC);
                        ch.pipeline().addLast(new IdleStateHandler(5, 0, 0));
                        //利用空闲检测Handler,处理那些客户端假死状态的问题,对于假死或者其他问题,及时清理资源,释放连接
                        //netty提供了IdleStateHandler, 读空闲和写空闲,2者都有,当超过指定直接后,没有数据产生,就会产生事件
                        //IdleState.READER_IDLE 读空闲事件 IdleState.WRITE_IDLE 写空闲时间 都空闲:IdleState.ALL_IDLE
                        ch.pipeline().addLast(LOGIN_HANDLER);
                        ch.pipeline().addLast(CHAT_HANDLER);
                        ch.pipeline().addLast(GROUP_CREATE_HANDLER);
                        ch.pipeline().addLast(GROUP_JOIN_HANDLER);
                        ch.pipeline().addLast(GROUP_CHAT_HANDLER);
                        ch.pipeline().addLast(QUIT_HANDLER);
                        //使用netty提供的ChannelDuplexHandler,处理自定义事件
                        ch.pipeline().addLast(new ChannelDuplexHandler(){
                            @Override
                            public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
                                IdleStateEvent event = (IdleStateEvent) evt;
                                if (event.state() == IdleState.READER_IDLE) {
                                    log.debug("已经5秒没有读到数据了.........");
                                    //关闭channel
                                    ctx.channel().close();
                                }
                            }
                        });
                    }
                }).bind(8080);
        future.sync();
    }

}
